﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using SarkoCut.Commands;
using System.IO;
using SarkoCut.Model;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Forms;

namespace SarkoCut.ViewModel
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private Dictionary<string, string> _pattern;
        private Dictionary<string, bool> _patternFound;

        private bool _isCueLoaded;
        public bool IsCueLoaded
        {
            get
            {
                return _isCueLoaded;
            }
            set
            {
                _isCueLoaded = value;
                OnPropertyChange("IsCueLoaded");
            }
           
        }

        #region Commands
        public ICommand Exit { get; set; }
        public ICommand OpenCue { get; set; }
        public ICommand SelectPath { get; set; }
        public ICommand Cut { get; set; }
        #endregion

        public MainModel Model { get; set; }

        public ObservableCollection<FileNamePreviewModel> FileNameListBox { get; set; }

        private string _path;
        public string Path
        {
            get
            {
                return _path;
            }
            set
            {
                _path = value;
                OnPropertyChange("Path");
            }
        }


        private ICollectionView _filenameView;
        public ICollectionView FilenameView
        {
            get
            {
                return _filenameView;
            }
        }

        public List<FileNameSettingsModel> Filenames { get; set; }

        FileNamePreviewModel FileNamePreview { get; set; }

        private Properties.Settings _mySettings;

        #region Konstruktor und Initialisierungsfunktionen
        public MainWindowViewModel()
        {            
            Model = new MainModel();
            FileNameListBox = new ObservableCollection<FileNamePreviewModel>();            
            FileNamePreview = new FileNamePreviewModel();

            _isCueLoaded = false;

            InitialiseCommandVariable();
            InitialiseSearchPattern();
            InitialiseComboboxSelectionChanged();
            
            
        }

        private void InitialiseSearchPattern()
        {
            InitialisePattern();
            InitialisePatternFound();
        }

        private void InitialisePattern()
        {
            _pattern = new Dictionary<string, string>();
            _pattern.Add("File", "FILE \"([A-Za-z -.]*)\" [A-Za-z]*");
            _pattern.Add("ReleaseDate", "REM DATE ([0-9]*)");
            _pattern.Add("Album", "TITLE \"([A-Za-z &,.öäüÖÄÜ'()/]*)");
            _pattern.Add("Artist", "PERFORMER \"([A-Za-z &,.öäüÖÄÜ'()/]*)");
            _pattern.Add("Filename", "TRACK ([0-9]{2}) [A-Z ]*TITLE \"([A-Za-z &,.öäüÖÄÜ'()/]*)\"[ ]*PERFORMER \"([A-Za-z &,.öäüÖÄÜ'()/]*)\"");
            //_pattern.Add("Time", "INDEX ([0-9]{2}) ([0-9:]*)");
        }

        private void InitialisePatternFound()
        {
            _patternFound = new Dictionary<string, bool>();
            _patternFound.Add("File", false);
            _patternFound.Add("ReleaseDate", false);
            _patternFound.Add("Album", false);
            _patternFound.Add("Artist", false);
            _patternFound.Add("Filename", false);
        }

        /// <summary>
        /// Die Combobox mit den Settings Werten füllen und auf die
        /// Veränderung der selektierten Auswahl registrieren
        /// </summary>
        private void InitialiseComboboxSelectionChanged()
        {
            // Hier wird die Combobox mit den Werten von den Settings gefüllt
            Filenames = new List<FileNameSettingsModel>();
            _mySettings = new Properties.Settings();
                        
            for (int i = 0; i < _mySettings.FileName.Count; i++)
            {
                FileNameSettingsModel Filename = new FileNameSettingsModel();
                Filename.FileName = _mySettings.FileName[i];
                Filenames.Add(Filename);
            }

            // registrieren der aktuellen Auswahl
            _filenameView = CollectionViewSource.GetDefaultView(Filenames);            
            _filenameView.CurrentChanged += new EventHandler(OnFilenameChanged);
        }

        /// <summary>
        /// Wenn sich die aktuelle Auwahl der Combobox ändert
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnFilenameChanged(object sender, EventArgs e)
        {
            FileNameListBox.Clear();
            if (IsCueLoaded && _filenameView.CurrentPosition > 0)
            {                
                SearchPattern(Model.CueFile, true);
            }            
                        
        }

        private void SetCueFileName()
        {

        }

        /// <summary>
        /// Initialisiert die Command Variablen
        /// </summary>
        private void InitialiseCommandVariable()
        {
            Exit = new ExitCommand();
            OpenCue = new OpenCueCommand(this);
            SelectPath = new SelectPathCommand(this);
            Cut = new CutCommand(this);
        }
  
        #endregion

        #region ExecuteCommand Funktionen
        /// <summary>
        /// Öffnet eine Cue Datei und zeigt den Inhalt in der linken Textblock an.
        /// </summary>
        public void OpenCueFile()
        {
            InitialisePatternFound();

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Cue Files (*.cue)|*.cue";

            //Nullable<bool> result = ofd.ShowDialog();
            //if (result == true)

            if(ofd.ShowDialog() == DialogResult.OK)
            {
                StreamReader reader = new StreamReader(ofd.OpenFile());
                StringBuilder lines = new StringBuilder();
                string line;

                while ((line = reader.ReadLine()) != null)
                {                    
                    lines.Append(line + "\n");
                }                               

                Model.CueFile = lines.ToString();                
                SearchPattern(lines.ToString());

                if (Model.FileExtension == "flac")
                    IsCueLoaded = true;
                /*
                else
                    MessageBox.Show("In der Cue Datei ist kein Verweis auf einer FLAC Datei");
                 */
            }
        }

        /// <summary>
        /// Auswahl eines Verzeichnisses
        /// </summary>
        public void SelectPathToStore()
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                Path = fbd.SelectedPath;                
            }
        }

        #endregion

        /// <summary>
        /// SearchPattern durchsucht das Dictionary _pattern mit Hilfe von Regulären Ausdrücken
        /// </summary>
        /// <param name="input">Der Text der durchsucht werden soll.</param>
        /// 
        private void SearchPattern(string input, bool filename = false)
        {
            input = input.Replace("\n", String.Empty);
            foreach (var pair in _pattern)
            {
                if (!_patternFound[pair.Key])
                {
                    Regex reg = new Regex(pair.Value);
                    if (reg.IsMatch(input))
                    {
                        Match match = reg.Match(input);
                        if (!filename)
                        {
                            switch (pair.Key)
                            {
                                case "File": string[] FilenamePieces = match.Groups[1].Value.Split('.'); Model.FileExtension = FilenamePieces[(FilenamePieces.Length - 1)]; _patternFound[pair.Key] = true; break;
                                case "Album": Model.Album = match.Groups[1].ToString(); _patternFound[pair.Key] = true; break;
                                case "Artist": Model.Artist = match.Groups[1].ToString(); _patternFound[pair.Key] = true; break;
                                case "ReleaseDate": Model.ReleaseDate = match.Groups[1].ToString(); _patternFound[pair.Key] = true; break;
                            } // end switch (pair.Key)
                            
                        }
                        else
                        {
                            while (match.Success)
                            {                                
                                FileNamePreview = new FileNamePreviewModel();
                                // Track
                                FileNamePreview.Track = match.Groups[1].ToString();
                                // Title
                                FileNamePreview.Titel = match.Groups[2].ToString();
                                // Artist
                                FileNamePreview.Artist = match.Groups[3].ToString();
                                //Album
                                FileNamePreview.Album = Model.Album;

                                if (_filenameView.CurrentPosition > 0)
                                {
                                    string[] FilenameComboboxArraySplit = Filenames[_filenameView.CurrentPosition].FileName.Split('-');
                                    FileNamePreview.FilenamePreview = String.Empty;
                                    for (int i = 0; i < FilenameComboboxArraySplit.Length; i++)
                                    {

                                        switch (FilenameComboboxArraySplit[i].Trim())
                                        {
                                            case "Track": if (FileNamePreview.FilenamePreview == String.Empty)
                                                    FileNamePreview.FilenamePreview += FileNamePreview.Track;
                                                else
                                                    FileNamePreview.FilenamePreview += " - " + FileNamePreview.Track;
                                                break;
                                            case "Titel": if (FileNamePreview.FilenamePreview == String.Empty)
                                                    FileNamePreview.FilenamePreview += FileNamePreview.Titel;
                                                else
                                                    FileNamePreview.FilenamePreview += " - " + FileNamePreview.Titel;
                                                break;

                                            case "Artist": if (FileNamePreview.FilenamePreview == String.Empty)
                                                    FileNamePreview.FilenamePreview += FileNamePreview.Artist;
                                                else
                                                    FileNamePreview.FilenamePreview += " - " + FileNamePreview.Artist;
                                                break;

                                            case "Album": if (FileNamePreview.FilenamePreview == String.Empty)
                                                    FileNamePreview.FilenamePreview += FileNamePreview.Album;
                                                else
                                                    FileNamePreview.FilenamePreview += " - " + FileNamePreview.Album;
                                                break;
                                        }
                                    } // end for (int i = 0; i < FilenameComboboxArraySplit.Length; i++)
                                    FileNamePreview.FilenamePreview += '.' + Model.FileExtension;
                                    FileNameListBox.Add(FileNamePreview);                                    
                                } // end if (_filenameView.CurrentPosition > 0)
                                match = match.NextMatch();
                               
                            }

                        }
                        

                    } // end if (reg.IsMatch(input))

                } // end if (!_patternFound[pair.Key])
            } // end foreach (var pair in _pattern)
        }

        #region Property changes
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Sobald sich eine Property ändert, wird es der View mitgeteilt
        /// </summary>
        /// <param name="propertyName">Property bzw. Eigebschaftsname</param>
        public void OnPropertyChange(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}
